/*****************************************************************************
*名称:	时间工具包
*功能:	获取时间的节点以及时间的时间段加减操作
*作者:	钱纯净
******************************************************************************/
package times

import (
	"fmt"
	"log"
	"strings"
	"time"
)

type times struct {
	time int64 //秒
	//nanosecond int64 //纳秒,纳秒太快,加计算控制不住时间的准确性,基础误差0.03-0.01秒
	start int64 //用于打印输出用时
}

//取当前时间
func Now() times {
	t := time.Now()
	return times{
		time: t.Unix(),
		//Nanosecond: t.UnixNano(),
		start: t.UnixNano(),
	}
}

//新建时间,秒
func New(n int64) times {
	return times{
		time:  n,
		start: time.Unix(n, 0).UnixNano(),
	}
}

//对应time.Unix()
func Unix(n int64) times {
	return times{
		time:  n,
		start: time.Unix(n, 0).UnixNano(),
	}
}

//string类型转time
func String(s string) (times, error) {
	time, err := time.ParseInLocation("2006-01-02 15:04:05", s, time.Local)
	if err == nil {
		return times{}, err
	}
	return times{
		time:  time.Unix(),
		start: time.UnixNano(),
	}, nil
}

func Date(year, month, day, hour, min, second int) times {
	return times{time: time.Date(year, time.Month(month), day, hour, min, second, 0, time.Local).Unix()}
}

//转为时间戳
func (this times) Unix() int64 {
	return this.time
}

//转为字符串,格式比如 "年-月-日 时-分-秒"
func (this times) String(s ...string) string {
	var str string

	if len(s) > 0 {
		str = strings.Replace(s[0], "年", "2006", -1)
		str = strings.Replace(str, "月", "01", -1)
		str = strings.Replace(str, "日", "02", -1)
		str = strings.Replace(str, "时", "15", -1)
		str = strings.Replace(str, "分", "04", -1)
		str = strings.Replace(str, "秒", "05", -1)
		str = time.Unix(this.time, 0).Format(str)
	} else {
		//0.4秒
		str = time.Unix(this.time, 0).Format("2006-01-02 15:04:05")
	}
	return str
}

//
//年月日秒
func (this times) Date() (int, int, int, int) {
	year, month, day := this.ToTime().Date()
	second := this.Unix() - this.IntegerDay().Unix()
	return year, int(month), day, int(second)
}

//********************************************分界线**************************************************//

//变成标准库的time
func (this times) ToTime() time.Time {
	return time.Unix(this.time, 0)
}

//秒,加减
func (this times) Add(a int) times {
	this.time += int64(a)
	return this
}

// //秒,加减
// func (this times) AddSec(a int) times {
// 	this.time += int64(a)
// 	return this
// }

// //分,加减
// func (this times) AddMin(a int) times {
// 	this.time += int64(a) * 60
// 	return this
// }

//小时加减
func (this times) AddHour(a int) times {
	this.time += int64(a) * 60 * 60
	return this
}

//天,加减
func (this times) AddDay(a int) times {
	this.time += int64(a) * 60 * 60 * 24
	return this
}

//周,加减
func (this times) AddWeek(a int) times {
	this.time = time.Unix(this.time, 0).AddDate(0, 0, a*7).Unix()
	return this
}

//月,加减
func (this times) AddMonth(a int) times {
	this.time = time.Unix(this.time, 0).AddDate(0, a, 0).Unix()
	return this
}

//年,加减
func (this times) AddYear(a int) times {
	this.time = time.Unix(this.time, 0).AddDate(a, 0, 0).Unix()
	return this
}

//************************************************分界线**********************************************//

//取整分
func (this times) IntegerMin() times {
	this.time = this.time - this.time%60
	return this
}

//取整点
func (this times) IntegerHour() times {
	this.time = this.time - this.time%(60*60)
	return this
}

//取整天
func (this times) IntegerDay() times {
	this.time = this.time - (this.time+60*60*8)%(60*60*24)
	return this
}

//取整周,周一
func (this times) IntegerWeek() times {
	t := int(time.Unix(this.time, 0).Weekday())
	this.time = this.AddDay(-t + 1).IntegerDay().Unix()

	return this
}

//取整月,速度快了40%
func (this times) IntegerMonth(a ...int) times {
	year, month, _ := time.Unix(this.time, 0).Date()
	this.time = time.Date(year, month, 1, 0, 0, 0, 0, time.Local).Unix()
	return this
}

//取整年,速度快了40%
func (this times) IntegerYear() times {
	year, _, _ := time.Unix(this.time, 0).Date()
	this.time = time.Date(year, 1, 1, 0, 0, 0, 0, time.Local).Unix()
	return this
}

//********************************************************分界线**********************************************************//

//返回用时的int64类型
func (this times) SpendInt64() int64 {
	return time.Now().UnixNano() - this.start
}

//返回用时的int64类型,单位秒 spendSecond
func (this times) SpendSecond() float64 {
	return float64(this.SpendInt64()) / (1000 * 1000 * 1000)
}

//返回用时的string类型
func (this times) SpendString(v ...string) string {
	var s string
	for _, v := range v {
		s += v
	}
	s += "用时:"
	t := this.SpendInt64()

	if t < 1000 {
		return fmt.Sprint(s, t, "纳秒")
	} else if t < 1000 {
		return fmt.Sprint(s, float64(t)/(1000), "微秒")
	} else if t < 1000*1000 { //通过这个调节精度
		return fmt.Sprint(s, float64(t)/(1000*1000), "毫秒")
	} else {
		return fmt.Sprint(s, float64(t)/(1000*1000*1000), "秒")
	}
}

//打印输出用时,单位秒
func (this times) Spend(v ...string) {
	log.Println(this.SpendString(v...))
}
